/**
 *                            License
 * THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS  
 * CREATIVE COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). 
 * THE WORK IS PROTECTED BY COPYRIGHT AND/OR OTHER APPLICABLE LAW.  
 * ANY USE OF THE WORK OTHER THAN AS AUTHORIZED UNDER THIS LICENSE OR  
 * COPYRIGHT LAW IS PROHIBITED.
 * 
 * BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND  
 * AGREE TO BE BOUND BY THE TERMS OF THIS LICENSE. TO THE EXTENT THIS LICENSE  
 * MAY BE CONSIDERED TO BE A CONTRACT,
 * THE LICENSOR GRANTS YOU THE RIGHTS CONTAINED 
 * HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND CONDITIONS.
 * 
 */
package lineage.packet;

import lineage.config.L1Config;
import lineage.core.L1GameClient;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 客户端封包的抽象类.
 * 
 * @version 2014年3月10日下午10:00:38
 * @author jrwz
 */
public abstract class L1AbstractPacketClient {
    private static final Logger LOG = LoggerFactory.getLogger(L1AbstractPacketClient.class);
    /** 客户端编码. */
    private static final String CLIENT_LANGUAGE_CODE = L1Config.CLIENT_LANGUAGE_CODE;
    private byte[] data = null;
    private int off = 0;

    /**
     * 处理客户端封包.
     * 
     * @param client
     *            - 客户端对象
     * @param data
     *            - 要处理的数据
     */
    public abstract void execute(final L1GameClient client, final byte[] data);

    /**
     * 初始化.
     * 
     * @param data
     *            - 数据
     */
    protected void init(final byte[] data) {
        try {
            this.data = data;
            off = 1; // 忽略第一个封包
        } catch (final Exception e) {
            LOG.error(e.getLocalizedMessage(), e);
        }
    }

    /**
     * 从'byte数组'中取回一个byte值.
     * 
     * @return 出错则返回0
     */
    protected int readC() {
        int i = 0x00;
        try {
            if (data == null) {
                return i;
            }
            if (data.length < off + 1) {
                return i;
            }
            i = data[off++] & 0xff;
            return i;
        } catch (final Exception e) {
        }
        return 0x00;
    }

    /**
     * 从'byte数组'中取回一个int值.
     * 
     * @return 出错则返回0
     */
    protected int readD() {
        int i = 0x00;
        try {
            if (data == null) {
                return i;
            }
            if (data.length < off + 4) {
                return i;
            }

            i = data[off++] & 0xff;
            i |= data[off++] << 8 & 0xff00;
            i |= data[off++] << 16 & 0xff0000;
            i |= data[off++] << 24 & 0xff000000;
            return i;
        } catch (final Exception e) {
        }
        return 0x00;
    }

    /**
     * 从'byte数组'中取回一个short值.
     * 
     * @return 出错则返回0
     */
    protected int readH() {
        int i = 0x00;
        try {
            if (data == null) {
                return i;
            }
            if (data.length < off + 2) {
                return i;
            }
            i = data[off++] & 0xff;
            i |= data[off++] << 8 & 0xff00;
            return i;
        } catch (final Exception e) {
        }
        return 0x00;
    }

    /**
     * 从'byte数组'中取回一个short值.
     * 
     * @return 出错则返回0
     */
    protected int readCH() {
        int i = 0x00;
        try {
            if (data == null) {
                return i;
            }
            if (data.length < off + 3) {
                return i;
            }
            i = data[off++] & 0xff;
            i |= data[off++] << 8 & 0xff00;
            i |= data[off++] << 16 & 0xff0000;
            return i;
        } catch (final Exception e) {
        }
        return 0x00;
    }

    /**
     * 从'byte数组'中取回一个double值.
     * 
     * @return 出错则返回0
     */
    protected double readF() {
        try {
            if (data == null) {
                return 0D;
            }
            if (data.length < off + 8) {
                return 0D;
            }
            long l = data[off++] & 0xff;
            l |= data[off++] << 8 & 0xff00;
            l |= data[off++] << 16 & 0xff0000;
            l |= data[off++] << 24 & 0xff000000;
            l |= (long) data[off++] << 32 & 0xff00000000L;
            l |= (long) data[off++] << 40 & 0xff0000000000L;
            l |= (long) data[off++] << 48 & 0xff000000000000L;
            l |= (long) data[off++] << 56 & 0xff00000000000000L;
            return Double.longBitsToDouble(l); // 返回对应于给定的位表示的double值
        } catch (final Exception e) {
        }
        return 0D;
    }

    /**
     * 从'byte数组'中取回一个String值.
     * 
     * @return 出错则返回null
     */
    protected String readS() {
        String s = null;
        try {
            if (data == null) {
                return s;
            }
            s = new String(data, off, data.length - off, CLIENT_LANGUAGE_CODE);
            s = s.substring(0, s.indexOf('\0'));
            off += s.getBytes(CLIENT_LANGUAGE_CODE).length + 1;
            return s;
        } catch (final Exception e) {
        }
        return null;
    }

    /**
     * 从'byte数组'中取回一组'byte数组'.
     * 
     * @return 出错则返回null
     */
    protected byte[] readByte() {
        byte[] result = null;
        try {
            result = new byte[data.length - off];
            // 从指定源数组中复制一个数组，复制从指定的位置开始，到目标数组的指定位置结束。
            System.arraycopy(data, off, result, 0, data.length - off);
            off = data.length;
            return result;
        } catch (final Exception e) {
        }
        return null;
    }

    /**
     * 清空.
     */
    protected void close() {
        try {
            data = null;
            off = 0;
        } catch (final Exception e) {
            LOG.error(e.getLocalizedMessage(), e);
        }
    }

    /**
     * 取得'客户端封包类型'的字符串信息.
     * 
     * @param 字符串信息
     */
    public String getType() {
        return "[C] " + this.getClass().getSimpleName();
    }
}
